////////////////////////////////////////////////////////////////////////////////
//
//  FLEX USER GROUP HOKURIKU
//  Copyright 2009 Flex User Group Hokuriku
//  All Rights Reserved.
// 
//  NOTICE: Flex User Group Hokuriku permits you to use, 
//  modify, and distribute this file 
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////
package net.fxug.hokuriku.chocolat.view
{
    import flash.display.Bitmap;
    import flash.display.BlendMode;
    import flash.display.NativeWindow;
    import flash.display.NativeWindowInitOptions;
    import flash.display.NativeWindowSystemChrome;
    import flash.display.NativeWindowType;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.DropShadowFilter;
    import flash.geom.Matrix;
    import flash.net.URLRequest;
    import flash.net.navigateToURL;
    import flash.text.TextField;
    import flash.text.TextFormat;

    import mx.logging.ILogger;

    import net.fxug.hokuriku.chocolat.utils.LoggingUtil;

    /**
     * 通知ウィンドウクラス
     *
     * @author shoito
     */
    public class NotificationWindow extends NativeWindow
    {
        private static const GOOD_BAD_WIDTH:int = 52;
        private static const ICON_SIZE:int = 32;
        private static const COMMENT_WIDTH:int = 220;
        private static const WIDTH:int = 280;
        private static const HEIGHT:int = 64;
        private static const VERTICAL_GUTTER:int = 5;
        private static const HORIZONTAL_GUTTER:int = 10;
        private static const ROUND:int = 20;

        private static const GOOD_COLOR:uint = 0x00BB00;
        private static const BAD_COLOR:uint = 0xBB0000;

        private static var logger:ILogger = LoggingUtil.getLogger(NotificationWindow);

        private const userNameFormatter:TextFormat = new TextFormat("arial", 12, 0xe4e4e4);
        private const commentFormatter:TextFormat = new TextFormat("arial", 16, 0xe4e4e4);

        /**
         * 通知ウィンドウの表示時間(min)
         */
        public var timeToLive:uint;

        /**
         * 通知ウィンドウのマネージャーインスタンス
         */
        private var manager:NotificationManager;

        [Embed(source='/assets/images/good_hand.png')]
        private var Good:Class;

        [Embed(source='/assets/images/bad_hand.png')]
        private var Bad:Class;

        /**
         * 通知の種類(good, bad)
         */
        private var notifyType:String;

        /**
         * 通知ウィンドウコンストラクタ
         *
         * @param manager NotificationManager
         * @param notifyType 通知種類(good, bad)
         * @param comment コメント
         * @param userName 送信者名
         * @param link 関連リンク情報
         */
        public function NotificationWindow(manager:NotificationManager, notifyType:String = NotificationManager.NOTIFY_GOOD, comment:String = "", userName:String = "", link:String = null):void
        {
            this.manager = manager;
            this.notifyType = notifyType;

            var options:NativeWindowInitOptions = new NativeWindowInitOptions();
            options.type = NativeWindowType.LIGHTWEIGHT;
            options.systemChrome = NativeWindowSystemChrome.NONE;
            options.transparent = true;
            super(options);

            initializeContents(notifyType, comment, userName, link);
        }

        private function initializeContents(notifyType:String, comment:String, userName:String, link:String):void
        {
            this.alwaysInFront = true;
            this.width = GOOD_BAD_WIDTH;
            this.height = HEIGHT;

            this.stage.addEventListener(MouseEvent.MOUSE_DOWN, function(mouseEvent:MouseEvent):void
                {
                    clickHandler(mouseEvent, link);
                });
            this.stage.align = StageAlign.TOP_LEFT;
            this.stage.scaleMode = StageScaleMode.NO_SCALE;

            this.manager.addEventListener(NotificationManager.LIFE_TICK_EVENT, this.lifeTick, false, 0, true);

            var IconClass:Class = (notifyType == NotificationManager.NOTIFY_GOOD) ? Good : Bad;
            addIcon(IconClass);
            addUser(userName);
            addComment(comment);

            drawBackground(notifyType);
        }

        private function addIcon(IconClass:Class):void
        {
            var icon:Sprite = getIcon(IconClass);
            this.stage.addChild(icon);
            icon.x = HORIZONTAL_GUTTER;
            icon.y = VERTICAL_GUTTER;
        }

        private function addUser(userName:String):void
        {
            var userText:TextField = new TextField();
            userText.text = userName;
            userText.wordWrap = true;
            userText.setTextFormat(userNameFormatter);
            this.stage.addChild(userText);
            userText.x = HORIZONTAL_GUTTER;
            userText.y = ICON_SIZE + VERTICAL_GUTTER;
        }

        private function addComment(comment:String):void
        {
            var commentText:TextField = new TextField();
            commentText.text = comment;
            commentText.wordWrap = true;
            commentText.setTextFormat(commentFormatter);
            this.stage.addChild(commentText);
            commentText.x = GOOD_BAD_WIDTH;
            commentText.y = VERTICAL_GUTTER;
            this.width = HORIZONTAL_GUTTER + GOOD_BAD_WIDTH + commentText.textWidth + HORIZONTAL_GUTTER;
        }

        private function clickHandler(event:MouseEvent, link:String = null):void
        {
            // Ctr+クリックの場合で、かつTwitterのつぶやきの場合はデフォルトブラウザで開く。
            if (event.ctrlKey && link != null)
            {
                try
                {
                    navigateToURL(new URLRequest(link), "_blank");
                }
                catch (e:Error)
                {
                    // Openに失敗した場合は、エラーを吐いてUI上は処理を実行する。
                    logger.error(e.getStackTrace());
                }
            }
            close();
        }

        /**
         * 表示してから一定時間後にクローズする
         *
         * @param event
         */
        public function lifeTick(event:Event):void
        {
            this.timeToLive--;
            if (this.timeToLive < 1)
            {
                close();
            }
        }

        /**
         * 通知ウィンドウを閉じる
         */
        public override function close():void
        {
            this.manager.removeEventListener(NotificationManager.LIFE_TICK_EVENT, this.lifeTick, false);
            super.close();
        }

        /**
         * 通知ウィンドウの背景を描画する
         * @param notifyType good/bad
         * @see http://d.hatena.ne.jp/nitoyon/20070801/as3_iphone_button テック煮さんに感謝
         */
        private function drawBackground(notifyType:String):void
        {
            var baseColor:uint = (notifyType == NotificationManager.NOTIFY_GOOD) ? GOOD_COLOR : BAD_COLOR;

            var background:Sprite = new Sprite();
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(this.width, this.height, Math.PI / 2);

            var base:Shape = new Shape();
            base.graphics.beginFill(baseColor, 0.75);
            base.graphics.drawRoundRect(0, 0, this.width, this.height, ROUND, ROUND);
            background.addChild(base);

            var border:Shape = new Shape();
            border.graphics.lineStyle(1, 0xffffff, 1);
            border.graphics.lineGradientStyle("linear", [0xffffff, 0xffffff, 0xffffff], [1, 0.3, 1], [0, 128, 255], matrix);
            border.graphics.drawRoundRect(1, 1, this.width - 2, this.height - 2, ROUND, ROUND);
            border.blendMode = BlendMode.OVERLAY;
            background.addChild(border);

            var glowTop:Shape = new Shape();
            glowTop.graphics.beginGradientFill("linear", [0xffffff, 0xffffff], [1, 0.2], [0, 128], matrix);
            glowTop.graphics.drawEllipse(-this.width / 2, -this.height / 2, this.width * 2, this.height);
            glowTop.blendMode = BlendMode.OVERLAY;
            background.addChild(glowTop);

            var mask:Shape = new Shape();
            mask.graphics.beginFill(0);
            mask.graphics.drawRoundRect(0, 0, this.width, this.height, ROUND, ROUND);
            background.addChild(mask);
            glowTop.mask = mask;

            var glowBottom:Shape = new Shape();
            glowBottom.graphics.beginGradientFill("linear", [0xffffff, 0xffffff], [0, 1], [224, 255], matrix);
            glowBottom.graphics.drawRoundRect(0, 0, this.width, this.height, ROUND, ROUND);
            glowBottom.blendMode = BlendMode.OVERLAY;
            background.addChild(glowBottom);

            var filter:DropShadowFilter = new DropShadowFilter(2, 90, 0x000000, 0.7);
            base.filters = [filter];

            this.stage.addChildAt(background, 0);
        }

        private function getIcon(IconClass:Class):Sprite
        {
            var image:Sprite = new Sprite();
            var bitmap:Bitmap = new IconClass();
            bitmap.width = ICON_SIZE;
            bitmap.height = ICON_SIZE;
            bitmap.smoothing = true;
            image.addChild(bitmap);
            return image;
        }
    }
}